package com.witdata.common.service.impl;

import com.mybatisflex.core.query.QueryWrapper;
import com.witdata.mysql.base.service.PermBaseService;
import com.witdata.mysql.base.service.RoleBaseService;
import com.witdata.mysql.base.service.RolePermBaseService;
import com.witdata.mysql.base.service.UserRoleBaseService;
import com.witdata.common.domain.Status;
import com.witdata.common.domain.dto.RoleDto;
import com.witdata.common.domain.dto.RolePermDto;
import com.witdata.common.domain.dto.RoleUserDto;
import com.witdata.mysql.domain.entity.TRole;
import com.witdata.mysql.domain.entity.TRolePerm;
import com.witdata.mysql.domain.entity.TUserRole;
import com.witdata.common.exception.GlobalException;
import com.witdata.common.mapper.RoleMapper;
import com.witdata.common.util.SnowflakeUtils;
import com.witdata.common.service.RoleService;
import com.witdata.common.util.IdUtils;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Service
@RequiredArgsConstructor
public class RoleServiceImpl implements RoleService {

    private final RoleBaseService roleBaseService;
    private final UserRoleBaseService userRoleBaseService;
    private final RolePermBaseService rolePermBaseService;
    private final PermBaseService permBaseService;
    private final HttpServletRequest request;
    private final SnowflakeUtils snowflakeUtils;

    @Override
    public List<String> getRoleCodeListByUserId(Long userId) {
        List<TRole> tRoleList = getRoleListByUserId(userId);
        return tRoleList.stream().map(TRole::getCode).toList();
    }

    @Override
    public List<Long> getRoleIdListByUserId(Long userId) {
        List<TRole> tRoleList = getRoleListByUserId(userId);
        return tRoleList.stream().map(TRole::getId).toList();
    }

    @Override
    public Set<String> getRoleCodeSetByUserId(Long userId) {
        List<String> roleCodeList = getRoleCodeListByUserId(userId);
        return new HashSet<>(roleCodeList);
    }

    @Override
    public Set<RoleDto> getRoleSetByUserId(Long userId) {
        List<TRole> tRoleList = getRoleListByUserId(userId);
        List<RoleDto> roleDtoList = RoleMapper.INSTANCE.toRoleDtoList(tRoleList);
        return new HashSet<>(roleDtoList);
    }

    @Override
    public void addPerm(RolePermDto rolePerm) {
        Long roleId = roleBaseService.getOne(new QueryWrapper().eq("name",rolePerm.getRoleName())).getId();
        Long permId = permBaseService.getOne(new QueryWrapper().eq("name",rolePerm.getPermName())).getId();
        boolean exists = rolePermBaseService.exists(new QueryWrapper().eq("role_id",roleId).eq("perm_id",permId));
        if(exists)throw new GlobalException(Status.ROLEPERMALREADYEXISTS);
        rolePermBaseService.save(TRolePerm.builder()
                .id(snowflakeUtils.nextId())
                .roleId(roleId)
                .permId(permId)
                .build());
    }

    @Override
    public void saveRole(RoleDto roleDto) {
        if (ObjectUtils.isEmpty(roleDto) || ObjectUtils.isEmpty(roleDto.getCode()) || ObjectUtils.isEmpty(roleDto.getName()))
            throw new GlobalException(Status.PARAMERROR);
        boolean exists = roleBaseService.exists(new QueryWrapper().eq("code", roleDto.getCode()));
        if (exists) throw new GlobalException(Status.ROLEALREADYEXISTS);
        long id = snowflakeUtils.nextId();
        TRole tRole = RoleMapper.INSTANCE.toTRole(roleDto);
        tRole.setId(id);
        tRole.setCreateTime(LocalDateTime.now());
        tRole.setCreateBy((Long) request.getAttribute("userId"));
        boolean save = roleBaseService.save(tRole);
        if (!save) throw new GlobalException(Status.ROLESAVEERROR);
    }

    @Override
    public List<RoleDto> getRoleList() {
        List<TRole> tRoleList = roleBaseService.list();
        return RoleMapper.INSTANCE.toRoleDtoList(tRoleList);
    }

    @Override
    public void addUser(RoleUserDto roleUser) {
        Long roleId = roleBaseService.getOne(new QueryWrapper().eq("name",roleUser.getRoleName())).getId();
        boolean exists = userRoleBaseService.exists(new QueryWrapper().eq("user_id",roleUser.getUserId()).eq("role_id",roleId));
        if(exists)throw new GlobalException(Status.USERROLEALREADYEXISTS);
        userRoleBaseService.save(TUserRole.builder()
                .id(snowflakeUtils.nextId())
                .roleId(roleId)
                .userId(roleUser.getUserId())
                .build());
    }

    public List<TRole> getRoleListByUserId(Long userId) {
        List<TUserRole> userRoleList = userRoleBaseService.list(new QueryWrapper().eq("user_id", userId));
        if (CollectionUtils.isEmpty(userRoleList)) return new ArrayList<>();
        List<TRole> tRoleList = roleBaseService.listByIds(userRoleList.stream().map(TUserRole::getRoleId).toList());
        if (CollectionUtils.isEmpty(tRoleList)) return new ArrayList<>();
        return tRoleList;
    }


}
